Skip to content

docs(runtime): assess evidence boundaries and specify artifact identity validation - #328

Merged
PhysShell merged 6 commits into
mainfrom
claude/runtime-evidence-contract-6147se
Aug 9, 2026
Merged

docs(runtime): assess evidence boundaries and specify artifact identity validation#328
PhysShell merged 6 commits into
mainfrom
claude/runtime-evidence-contract-6147se

Conversation

@PhysShell

Copy link
Copy Markdown
Owner

Что и зачем

Оценка внешнего предложения по рантайм-слою, проверенная по дереву, и вышедший из неё измеренный контрактный дефект со scoped-спекой. Никаких изменений в рантайм-реализации, никакого кода.

Сразу, чтобы снять предсказуемое недоразумение при чтении первой трети диффа:

  • Никаких изменений в рантайме. Дифф целиком документационный.
  • Issue по задаче не заводится. Канонической поверхностью остаётся docs/tasks/runtime-artifact-identity.md.
  • Спека ready to implement, но намеренно не запланирована в текущую очередь.
  • Leaf — это триггер оценки, а не зависимость и не предлагаемая интеграция. Rust MIR к CLR никто не прикручивает.

Что было проверено и что нашлось:

Предложение опиралось на то, что Rust-фреймворк инструментации станет провайдером рантайм-evidence для OwnAudit. По дереву это не строится: OwnAudit аудирует .NET 4.7.2 / WPF (98 .sarif, 70 .py, 31 .cs, ноль .rs), рантайм-половина — обход кучи через ClrMD. В .NET нет MIR. Инвариант, вызвавший ошибку, записан отдельно, потому что она естественная и повторится: язык реализации ядра ≠ анализируемый язык — P-022 переносит реализацию анализатора на Rust и не делает Rust целью анализа.

Из пяти предложенных к заимствованию идей две уже отгружены, одна отгружена как паттерн, у одной уже есть шов, а одна решает проблему стоимости, которой у этого стека нет. Но проверка вскрыла настоящий дефект:

Все четыре отгруженных семейства рантайм-артефактов имеют проблему идентичности — у heap-retention две конфликтующие (own-runtime/1 против ownAudit/runtime/v1, след незавершённого lift-out), у остальных трёх нет никакой. И ничто это не валидирует: correlate.py читает только retained/type/count/… и никогда не смотрит на schema, то есть любой JSON с массивом retained сегодня принимается как контракт.

Правильная граница при этом оказалась не там, где казалось: PropertyChangedStorm не собирает ETW, а читает уже захваченный .etl через ETWTraceEventSource. Значит слои — acquisition (attach/.dmp/.etl) → interpretation → артефакт, и общим заслуживает быть контракт артефакта, а не субстрат сбора. Поэтому первый шаг — версионирование по семействам, а общий конверт откладывается до момента, когда общность будет доказана четырьмя схемами, а не нарисована заранее.

Тип изменения

  • feat — новая возможность
  • fix — исправление бага
  • docs — документация
  • refactor / chore / test / ci — без изменения поведения

Как проверено

Поведение не меняется, менять нечего — поэтому тесты репозитория не применимы и не гонялись. Проверялись сами утверждения, каждое против дерева:

  • Состав OwnAudit — по shallow-клону main: счёт файлов по расширениям, отсутствие .rs/Cargo.toml.
  • Слои producer'ов — по API, которые каждый реально вызывает: ETWTraceEventSource/.etl у PropertyChangedStorm, LoadDump/procdump у DuplicateDetector и LeakHarness, AttachToProcess у RetentionPath.
  • Расхождение схем — по числу вхождений "schema": RetentionPath 2, OwnAudit.Runtime 1, остальные три по 0.
  • Отсутствие валидации — по полям, которые correlate.py реально читает, и по единственной существующей ассерции (HeapCollectorContractTests.cs:83, сверяющей producer с самим собой).
  • Относительные ссылки в обоих файлах проверены скриптом.

Существование, название, авторы и предмет статьи сверены с arXiv. Цифры накладных расходов сверены не мной и помечены в заметке как second-hand — они процитированы только чтобы показать, что мотивация одной из идей это стоимость.

Связанные issue

Нет, и это осознанно. Задача имеет статус spec, ready to implement, но намеренно не входит в текущую очередь; issue заводить сейчас означало бы создать вторую status-поверхность и две копии scope/acceptance для работы, которую мы сознательно не планируем — ровно тот дефект дублирующихся контрактов, который эта задача и чинит. Жизненный цикл и шаблон будущего тонкого issue-wrapper'а зафиксированы в §8 спеки.

Чеклист

  • изменение покрыто тестом/селфтестом (или объяснено, почему нет) — тестов нет: дифф документационный, а найденный дефект несёт собственную приёмочную матрицу в спеке, включая несущий кейс «валидно выглядящий retained[] с неправильной schema не должен скоррелироваться»
  • README/docs обновлены при необходимости — runtime-contract.md и код producer'ов намеренно не трогались: их правка и есть отложенная задача
  • коммиты в conventional-commit стиле (feat:, fix:, docs: …)

Коммиты намеренно не сквошены: последовательность (первоначальная ошибка → проверка по дереву → исправление модели → измеренный дефект → спека) и есть provenance того, почему задача вообще появилась.


Generated by Claude Code

claude added 5 commits August 9, 2026 17:27
An outside reading of arXiv:2607.15025 proposed Leaf as a concrete building
block for OwnAudit (8.5/10) with a separate Rust-analysis direction (9/10) and
five ideas to adopt. The paper is real and accurately summarised; the proposal
does not survive contact with the repositories.

Leaf instruments Rust MIR. OwnAudit audits .NET 4.7.2 / WPF -- 98 sarif, 70 py,
31 cs, zero .rs, no Cargo.toml, and a runtime half that is a ClrMD heap walk
emitting ownAudit/runtime/v1. There is no MIR in .NET and Leaf cannot observe a
CLR process, so the proposed adapter pipeline has no endpoints. The
Rust-analysis direction is further off: P-017 targets OwnTS and OwnJVM, and the
project's thesis is ownership discipline for a GC language that lacks it, which
Rust is not. The likely confusion is P-022 -- the analyzer written in Rust, not
analyzing Rust.

Of the five ideas: static-site/runtime-fact correlation and explicit evidence
gaps are already shipped, the oracle pattern is already shipped, the
provider-agnostic seam already exists as a versioned runtime.json schema, and
static-directed targeted instrumentation solves a per-event cost problem a
post-scenario heap snapshot does not have. The sharpest inversion is the
evidence-gap item, offered as something to import when it is already the
CI-proven exit-code contract in runtime-witness-operations.md.

Recorded so the proposal is not re-derived, same purpose as P-034's
do-not-re-derive table. The one genuine takeaway is about our own roadmap: the
runtime layer is single-purpose today while Plan.md schedules two more consumers
(storm frequency, duplicate heap data), so the shared-schema-vs-bespoke-collector
question is worth settling before the second collector exists.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PbyzyVi7fibuSKLweuXgea
…rs, not pending

Follow-up on the Leaf assessment after the original author accepted the
correction and refined the takeaway. Two changes, both from reading the tree
rather than from the paper.

Accepts the second concept-level takeaway: separate the collection substrate
from the analysis-facing representation. Leaf does not hand probes to analyzers
-- probes are shaped for cheap instrumentation and an adapter reconstructs
structured events -- and that boundary is what stops a snapshot and an event
stream being forced into one datatype.

Replaces "decide before the second dynamic consumer" with what is actually
there. audit/runtime/ already ships four collectors, so Plan.md categories 6 and
11 exist as code with bespoke JSON each. Two producers of runtime.json emit two
different schema strings -- RetentionPath says own-runtime/1, the newer
stand-side collector and docs and every fixture say ownAudit/runtime/v1 -- a
lift-out artifact, but live. Nothing enforces either: correlate.py reads only
retained/type/count/expected/bytes/roots/kind/holder/member and never touches
schema, scenario, iterations, collector or verdict, and the one assertion checks
a producer against itself. No impact today since the correlator ignores unknown
fields; the risk is latent and cheap to settle now.

Adds a caution the proposed hybrid needs: moving completeness into the envelope
collides with the existing fail-closed contract, where a refusal means exit 2
and no artifact at all. A completeness: PARTIAL field would create the first
valid-but-admittedly-incomplete artifact -- possibly right for an event trace,
but a weakening to decide deliberately, not inherit.

Records the invariant that caused the original error, since it will recur: do
not infer analyzed-language support from the implementation language of the
core. P-022 moves the analyzer's implementation to Rust; it does not change the
audited runtime or make Rust an analysis target.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PbyzyVi7fibuSKLweuXgea
…cts before unifying them

Two corrections and a resequencing, all verified against the tree.

Counting fix: the note said four C# collectors under Own.NET/audit/runtime and
then showed a five-row table, because the fifth row is the lift-out producer in
the other repository. There are four directories under audit/runtime and five
producer implementations across the two repos.

Terminology fix, and it is load-bearing rather than pedantic. "Collector"
conflated two layers. Checked by the APIs each one calls: PropertyChangedStorm
opens an ETWTraceEventSource over an .etl captured externally by
PerfView/xperf/logman and acquires nothing at all; DuplicateDetector and
LeakHarness interpret a .dmp and can shell out to procdump; RetentionPath does
AttachToProcess or LoadDump. So the layering is acquisition (live attach / .dmp
/ .etl) then interpretation then analysis-facing artifact. That sharpens the
takeaway: the acquisition representation should not be the evidence
representation, and what deserves sharing is a runtime artifact contract, not a
collection substrate. A .dmp and an .etl are already good acquisition
substrates; unifying them would unify the wrong layer.

Resequencing: a shared envelope is the right destination but the wrong first
move, since designing commonality up front is the mistake Leaf avoids. The
minimal work is per-family mandatory schema identity, then readers that validate
family and major version while staying tolerant of unknown fields, and only then
an envelope extracted from commonality proven by shipped schemas. Step two is
the actual gap: correlate() duck-types any dict carrying a retained array.

Splits completeness into collection outcome, artifact validity and evidence
coverage. Refusal still means exit 2 and no artifact; validity is the missing
layer; coverage belongs to the artifact family, so heap retention can stay
total-or-no-artifact while an ETW trace carries real bounds. Records the
invariant that artifact existence proves execution of the producer contract, not
completeness of observation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PbyzyVi7fibuSKLweuXgea
Fixes two errors in the assessment note and promotes the one finding that
earned it from recorded to a written work item.

Arithmetic fix: the note claimed four of five producers emit no version, which
contradicted its own table. Ground truth -- RetentionPath emits a schema string
twice, OwnAudit.Runtime once, and LeakHarness, DuplicateDetector and
PropertyChangedStorm emit none. Three of five, not four.

Recounts by artifact family instead, since families are what would be versioned:
five producer implementations emit four analysis-facing families, and all four
have an identity problem -- heap-retention carries two conflicting identities,
the other three carry none. Also drops a stale tail that still spoke of a fourth
consumer inheriting the ambiguity; four families and five producers already
exist, so the trigger is the artifact surface expanding further.

Adds docs/tasks/runtime-artifact-identity.md in the established task-spec
format. Scope is held deliberately small: one identity per shipped family, an
explicit compatibility decision for the heap-retention lift-out split, readers
that reject missing identity, wrong family and unsupported major while still
accepting unknown fields, and negative fixtures for every rejection case. The
load-bearing acceptance case is that a valid-looking retained[] payload with a
wrong or missing schema must not correlate -- without it the change is a
decorative equality check. A common envelope, any completeness enum, acquisition
changes and SARIF changes are all explicitly out of scope, with a guard telling
implementers to stop if they start designing a field every family would share.

Priority recorded as small correctness debt with high leverage: not a blocker,
sequenced after the boundary and gate work already in flight.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PbyzyVi7fibuSKLweuXgea
The spec said 'not scheduled' but not what happens when it is, so the default
next action was to copy 132 lines into a GitHub issue and mint a second
normative surface -- the same duplicate-contract defect this task exists to fix,
reproduced in our own process.

Records the decision: this file stays canonical, no issue is filed at this
stage, and when the task enters the execution queue the issue is a thin handle
carrying title, a pointer to this spec, why-now, live dependencies and the PR
link -- with scope and acceptance explicitly not duplicated. Also notes the
second reason to wait: the task spans both repositories and its heap-retention
compatibility decision is taken up front, so execution metadata frozen today
would be stale by the time work starts.

No code, no scope, no acceptance changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PbyzyVi7fibuSKLweuXgea
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@PhysShell, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 48 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 549e965a-82ed-4f42-a263-c5dd47c39401

📥 Commits

Reviewing files that changed from the base of the PR and between 5cf36c0 and cd0d771.

📒 Files selected for processing (2)
  • docs/notes/leaf-dmir-assessment.md
  • docs/tasks/runtime-artifact-identity.md

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0e9de19586

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/tasks/runtime-artifact-identity.md Outdated
Comment thread docs/tasks/runtime-artifact-identity.md Outdated
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

@coderabbitai review

…variant

Two valid findings from the Codex review on #328, both verified against the tree
before acting.

Reader scope was incomplete. audit/runtime/ingest.py is the active reader for
leak-growth, duplicate-immutable and propertychanged-storm -- it takes
--leak-harness / --duplicate-detector / --propertychanged-storm, does a bare
json.loads and emits SARIF with no identity check -- but the spec listed readers
only under OwnAudit/runtime/. Following it as written would have given three of
four families an identity nothing was required to validate, which is the defect
in miniature. Adds a reader table naming both repositories and points the
negative cases at ingest.py's existing --selftest.

The exit-2 invariant was over-generalized from RetentionPath's documented
contract. Checked per producer: DuplicateDetector and PropertyChangedStorm catch
Exception and return 2, but LeakHarness catches only ScenarioException, so a
missing scenario file, a failed process launch, a missing window or a failed
dump leaves Main with the unhandled-exception code. Requiring exit 2 across all
four families would therefore change collection semantics, which the task's own
out-of-scope list forbids. The requirement is now scoped to producers that
already implement it, with normalizing LeakHarness called out as a separate
labelled behaviour change. The same over-generalization is corrected in the
assessment note's collection-outcome bullet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PbyzyVi7fibuSKLweuXgea
@PhysShell
PhysShell merged commit cc267cb into main Aug 9, 2026
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants